﻿using System;
using System.Diagnostics;
using System.Web.Services.Protocols;
using System.Net.Mail;
using System.Configuration;
using System.IO;

namespace QueueManager.Helper
{
  public class LogHelper
  {

    public enum LogType
    {
      Information,
      Warning,
      Exception
    }


    public static void Log(string Message, Exception Ex, LogType Type)
    {
      EventLog objEvent = new EventLog();
      string strLog = null;
      SmtpClient objSmtp = default(SmtpClient);
      MailMessage objMail = default(MailMessage);
      string strNotify = null;
      string strSubject = null;

      strLog = Message;

      if (Ex != null)
      {
        if (Ex is SoapException)
        { 
          strLog += Environment.NewLine + Environment.NewLine + "Exception: " + Environment.NewLine + Ex.Message;
          strLog += Environment.NewLine + Environment.NewLine + "Details: " + Environment.NewLine + ((SoapException)Ex).Detail.InnerText;
        }
        else
        {
          strLog += Environment.NewLine + Environment.NewLine + "Exception: " + Environment.NewLine + Ex.Message;

          if (Ex.InnerException != null)
          {
            strLog += Environment.NewLine + Environment.NewLine + "InnerException: " + Environment.NewLine + Ex.InnerException.Message;
          }
        }
        strLog += Environment.NewLine + Environment.NewLine + "Stack trace: " + Environment.NewLine + Ex.StackTrace;
      }

      //Create the event log source

      if (ConfigurationManager.AppSettings["logeventlog"] == "true")
      {
        if (!System.Diagnostics.EventLog.SourceExists("CRMQueueManager"))
        {
          try
          {
            System.Diagnostics.EventLog.CreateEventSource("CRMQueueManager", "Application");
          }
          catch (Exception ex1)
          {
            //How to report now? Simply disable it.
          }
        }

        try
        {
          objEvent.Source = "CRMQueueManager";
          objEvent.Log = "Application";

          switch (Type)
          {
            case LogType.Exception:
              objEvent.WriteEntry(strLog, EventLogEntryType.Error);
              break;
            case LogType.Information:
              objEvent.WriteEntry(strLog, EventLogEntryType.Information);
              break;
            case LogType.Warning:
              objEvent.WriteEntry(strLog, EventLogEntryType.Warning);

              break;
          }
        }
        catch (Exception ex1)
        {
          //This can fail, simply ignore it
        }
      }

      if (Type == LogType.Exception)
      {
        if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["logerrornotify"]))
        {
          strNotify = ConfigurationManager.AppSettings["logerrornotify"];
          strSubject = "CRM Queue Manager Error";
        }
      }
      else if (Type == LogType.Warning)
      {
        if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["logwarningnotify"]))
        {
          strNotify = ConfigurationManager.AppSettings["logwarningnotify"];
          strSubject = "CRM Queue Manager Warning";
        }
      }

      //Log to console
      Output(strLog, true, true);

      if (!string.IsNullOrEmpty(strNotify))
      {
        objMail = new MailMessage(ConfigurationManager.AppSettings["lognotifyfrom"], strNotify);
        objSmtp = new SmtpClient();

        objMail.Subject = strSubject;
        objMail.IsBodyHtml = false;
        objMail.Body = strLog;

        try
        {
          //Workaround for Google
          if (objSmtp.Host.Contains("gmail"))
          {
            objSmtp.EnableSsl = true;
          }

          objSmtp.Send(objMail);
        }
        catch (Exception ex1)
        {
          try
          {
            objEvent.WriteEntry("Exception while sending error notification mail: " + Ex.Message, EventLogEntryType.Error);
          }
          catch (Exception ex2)
          {
            //Nothing more we can do 
          }
        }
      }

    }

    public static void Output(string strMessage, params string[] args)
    {
      Output(strMessage, true, args);
    }

    public static void Output(string strMessage, bool WriteTime, params string[] args)
    {
      Output(strMessage, WriteTime, false, args);
    }

    /// <summary>
    /// Output to console and file
    /// </summary>

    public static void Output(string strMessage, bool WriteTime, bool IsException, params string[] args)
    {
      string strText = null;
      string strFile = ConfigurationManager.AppSettings["logtofile"];

      if (args.Length > 0)
      {
        strText = string.Format(strMessage, args);
      }
      else
      {
        strText = strMessage;
      }

      if (WriteTime)
      {
        strText = string.Format("{0} {1}", DateTime.Now.ToString("HH:mm:ss"), strText);
      }

      if (Environment.UserInteractive)
      {
        if (IsException)
        {
          Console.ForegroundColor = ConsoleColor.Red;
        }

        Console.WriteLine(strText);

        if (IsException)
        {
          Console.ResetColor();
        }

      }

      if (!string.IsNullOrEmpty(strFile))
      {
        try
        {
          //Check if the file exist and create versions if it becomes to big. Only check every 20 time
          //to avoid checking file props for every line written.
          if (static_Output_intFileCheck > 20)
          {
            if (File.Exists(strFile))
            {
              var f = new FileInfo(strFile);
              if (f.Length > 50000)
              {
                //Rename the file to fileyyyymmddhhmm.ext
                File.Move(strFile, Path.Combine(Path.GetDirectoryName(strFile), string.Format("{0}{1}{2}", Path.GetFileNameWithoutExtension(strFile), DateTime.Now.ToString("yyyyMMddHHmm"), Path.GetExtension(strFile))));
              }
            }
            static_Output_intFileCheck = 0;
          }

          File.AppendAllText(ConfigurationManager.AppSettings["logtofile"], strText + Environment.NewLine);

        }
        catch (Exception ex)
        {
          //Do nothing
        }
        finally
        {
          static_Output_intFileCheck += 1;
        }

      }

    }
    static int static_Output_intFileCheck = 0;

  }
}
